package cn.jbolt.core.api;

import cn.jbolt.core.base.JBoltMsg;
import cn.jbolt.core.db.sql.Sql;
import cn.jbolt.core.db.util.JBoltTxKit;
import cn.jbolt.core.model.base.JBoltBaseModel;
import cn.jbolt.core.para.IJBoltParaValidator;
import cn.jbolt.core.para.JBoltParaValidator;
import cn.jbolt.core.service.base.IJBoltService;
import cn.jbolt.core.util.JBoltArrayUtil;
import cn.jbolt.core.util.JBoltDateUtil;
import com.jfinal.kit.Kv;
import com.jfinal.kit.Okv;
import com.jfinal.kit.Ret;
import com.jfinal.plugin.activerecord.Model;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.upload.UploadFile;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * Api Service底层通用封装
 *
 * @ClassName: CommonService
 * @author: JFinal学院-小木 QQ：909854136
 * @date: 2019年12月10日
 */
public abstract class JBoltApiCommonService implements IJBoltService,IJBoltParaValidator{
	protected static final String TRUE = Sql.TRUE;
	protected static final String FALSE = Sql.FALSE;

	/**
	 * 成功消息默认返回值
	 */
	protected static final Ret SUCCESS = Ret.ok(JBoltMsg.SUCCESS);
	/**
	 * 执行成功但是有警告
	 */
	protected static final Ret WARN = Ret.create().set("state","warn").set("msg","warning");
	/**
	 * 默认空KV
	 */
	protected static final Kv KV_EMPTY = Kv.create();
	/**
	 * 默认空OKV
	 */
	protected static final Okv OKV_EMPTY = Okv.create();
	/**
	 * 设置失败返回消息 默认设置需要回滚事务 但是 只有执行的方法设置了事务拦截才有效
	 * @return
	 */
	protected Ret fail() {
		return fail(JBoltMsg.FAIL,true);
	}
	/**
	 * 设置失败返回消息 默认设置需要回滚事务 但是 只有执行的方法设置了事务拦截才有效
	 *
	 * @param msg
	 * @return
	 */
	protected Ret fail(String msg) {
		return fail(msg,true);
	}


	/**
	 * 设置警告 意思是执行成功了 但是中间有警告 底层调用的就是success
	 * warn和success一样 没有事务回滚 只有fail有
	 * @param msg
	 * @return
	 */
	protected Ret warn(String msg) {
		return Ret.create().set("state","warn").set("msg",msg);
	}

	/**
	 * 设置警告 意思是执行成功了 但是中间有警告 底层调用的就是success
	 * warn和success一样 没有事务回滚 只有fail有
	 * @param msg
	 * @param data
	 * @return
	 */
	protected Ret warn(String msg,Object data) {
		return Ret.create().set("state","warn").set("msg",msg).set("data",data);
	}

	/**
	 * 设置失败返回消息
	 *
	 * @param msg
	 * @param isTxNeedCallback 是否需要回滚事务 但是 只有执行的方法设置了事务拦截才有效
	 * @return
	 */
	protected Ret fail(String msg,boolean isTxNeedCallback) {
		if(isTxNeedCallback){
			JBoltTxKit.setNeedRollback(true);
			JBoltTxKit.setErrorMsg(msg);
		}
		return Ret.fail(msg);
	}

	/**
	 * 自动判断返回值
	 *
	 * @param success
	 * @return
	 */
	protected Ret ret(boolean success) {
		return success ? SUCCESS : fail();
	}
	/**
	 * 过滤返回值 model专用
	 *
	 * @param ret
	 * @param columns
	 * @return
	 */
	protected Ret filterModelRet(Ret ret, String... columns) {
		if (columns == null) {
			return ret;
		}
		JBoltBaseModel<? extends JBoltBaseModel<?>> myModel = ret.getAs("data");
		if (columns.length == 1) {
			ret.set("data", myModel.get(columns[0]));
		} else {
			Kv kv = Kv.create();
			for (String column : columns) {
				kv.set("column", myModel.get(column));
			}
			ret.set("data", kv);
		}
		return ret;
	}

	/**
	 * 设置成功返回消息
	 *
	 * @param msg
	 * @return
	 */
	protected Ret success(String msg) {
		return Ret.ok(msg);
	}

	/**
	 * 设置成功返回消息 设置返回data
	 *
	 * @param data
	 * @return
	 */
	protected Ret successWithData(Object data) {
		return Ret.ok().set("data", data);
	}

	/**
	 * 设置成功返回值带着数据和消息
	 *
	 * @param data
	 * @param msg
	 * @return
	 */
	protected Ret success(Object data, String msg) {
		return Ret.ok(msg).set("data", data);
	}


	/**
	 * 判断Object参数有效性
	 *
	 * @param param
	 */
	@Override
	public boolean isOk(Object param) {
		return JBoltParaValidator.isOk(param);
	}

	/**
	 * 判断Object参数是否无效
	 */
	@Override
	public boolean notOk(Object param) {
		return JBoltParaValidator.notOk(param);
	}
	/**
	 * 判断record参数有效性
	 * @param record
	 */
	@Override
	public boolean isOk(Record record) {
		return JBoltParaValidator.isOk(record);
	}

	/**
	 * 判断record参数是否无效
	 * @param record
	 */
	@Override
	public boolean notOk(Record record) {
		return JBoltParaValidator.notOk(record);
	}
	/**
	 * 判断model参数有效性
	 * @param model
	 */
	@Override
	public boolean isOk(Model<? extends Model<?>> model) {
		return JBoltParaValidator.isOk(model);
	}

	/**
	 * 判断record参数是否无效
	 * @param model
	 */
	@Override
	public boolean notOk(Model<? extends Model<?>> model) {
		return JBoltParaValidator.notOk(model);
	}
	/**
	 * 判断Object参数为Null
	 * @param param
	 */
	@Override
	public boolean isNull(Object param){
		return JBoltParaValidator.isNull(param);
	}
	/**
	 * 判断Object参数不为Null
	 * @param param
	 */
	@Override
	public boolean notNull(Object param){
		return JBoltParaValidator.notNull(param);
	}
	/**
	 * 判断是否存在一个有效参数
	 * @param params
	 */
	@Override
	public boolean hasOk(Object... params) {
		return JBoltParaValidator.hasOk(params);
	}
	/**
	 * 判断是存在无效参数
	 * @param params
	 */
	@Override
	public boolean hasNotOk(Object... params) {
		return JBoltParaValidator.hasNotOk(params);
	}
	/**
	 * 判断上传文件是图片
	 * @param contentType
	 */
	@Override
	public boolean isImage(String contentType) {
		return JBoltParaValidator.isImage(contentType);
	}

	/**
	 * 判断上传文件不是图片
	 * @param contentType
	 */
	@Override
	public boolean notImage(String contentType) {
		return JBoltParaValidator.notImage(contentType);
	}

	/**
	 * 判断上传文件类型不是图片
	 * @param file
	 */
	@Override
	public boolean notImage(UploadFile file) {
		return JBoltParaValidator.notImage(file);
	}

	/**
	 * 判断上传文件类型是否为图片
	 * @param file
	 */
	@Override
	public boolean isImage(UploadFile file) {
		return JBoltParaValidator.isImage(file);
	}

	/**
	 * 判断Object[]数组类型数据是否正确
	 * @param param
	 * @return
	 */
	@Override
	public boolean isOk(Object[] param) {
		return JBoltParaValidator.isOk(param);
	}

	/**
	 * 判断Object[]数组类型数据不正确
	 * @param param
	 * @return
	 */
	@Override
	public boolean notOk(Object[] param) {
		return JBoltParaValidator.notOk(param);
	}
	/**
	 * 判断文件是否为excel
	 * @param file
	 * @return
	 */
	@Override
	public boolean notExcel(UploadFile file) {
		return JBoltParaValidator.notExcel(file);
	}
	/**
	 * 判断文件是否为excel
	 * @param file
	 * @return
	 */
	@Override
	public boolean isExcel(UploadFile file) {
		return JBoltParaValidator.isExcel(file);
	}


	/**
	 * 转为startTime
	 *
	 * @param startTime
	 * @param isOracle
	 * @return
	 */
	public String toStartTime(Date startTime,boolean isOracle) {
		return toDateTime(JBoltDateUtil.HHmmssTo000000Str(startTime),isOracle);
	}

	/**
	 * 转为endTime
	 *
	 * @param endTime
	 * @param isOracle
	 * @return
	 */
	public String toEndTime(Date endTime,boolean isOracle) {
		return toDateTime(JBoltDateUtil.HHmmssTo235959Str(endTime),isOracle);
	}

	/**
	 * 转为表达式处理date
	 *
	 * @param dateTime
	 * @return
	 */
	public String toDateTime(String dateTime,boolean isOracle) {
		if (isOracle) {
			return String.format("TO_DATE('%s','yyyy-mm-dd hh24:mi:ss')", dateTime);
		}
		return dateTime;
	}

	public String[] splitByLineToArray(String str,String... inlineSplitChars) {
		List<String> lines = splitByLineToList(str,inlineSplitChars);
		if(isOk(lines)){
			return lines.toArray(new String[0]);
		}
		return null;
	}

	public List<String> splitByLineToList(String str,String... inlineSplitChars) {
		if(notOk(str)){
			return null;
		}
		str = str.trim();
		String regex = "\\r?\\n";
		List<String> lines = Arrays.stream(str.split(regex))
				.map(String::trim)
				.filter(s -> !s.isEmpty())
				.collect(Collectors.toList());
		if(notOk(lines)){
			return null;
		}
		if(str.contains(",") || str.contains(" ")){
			String[] temps = null;
			List<String> tempList;
			List<String> rets = new ArrayList<>();
			String[] tempArr;
			String[] tempArr2;
			boolean has1=false;
			boolean has2=false;
			for(String line:lines){
				has1 = line.contains(",");
				has2 = line.contains(" ");
				if(has1&&!has2){
					temps =  JBoltArrayUtil.from(line);
				}else if(has2&!has1){
					temps =  JBoltArrayUtil.from(line," ");
				}else if(has1){
					tempList =new ArrayList<>();
					//第一步 用空格分
					tempArr = JBoltArrayUtil.from(line," ");
					if(isOk(tempArr)){
						//第二步 用逗号分
						for(String temp:tempArr){
							tempArr2 = JBoltArrayUtil.from(temp,",");
							if(isOk(tempArr2)){
								tempList.addAll(Arrays.asList(tempArr2));
							}
						}
					}
					if(isOk(tempList)){
						temps = tempList.toArray(new String[0]);
					}
				}else{
					temps = new String[]{line};
				}
				if(isOk(temps)){
					assert temps != null;
					rets.addAll(Arrays.asList(temps));
				}
			}
			return rets;
		}
		return lines;
	}
}
